using System.Collections.Generic;
using System.Linq;
using PEMath;
using UnityEngine;

/****************************************************
// 功能：战斗计算规则
// | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
// | Copyright (c) 2021-2025 聊来 All rights reserved.
// | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">聊来</a> )
// | @Author: 贯彻己道的云 <18970881148@qq.com>
// | DateTime: 2025/4/2 15:47:26
*****************************************************/

public static class CalcRule
{
    public static Hero[] blueTeamHero;
    public static Hero[] redTeamHero;
    public static Tower[] blueTeamTower;
    public static Tower[] redTeamTower;
    public static List<Soldier> blueTeamSoldier = new List<Soldier>();
    public static List<Soldier> redTeamSoldier = new List<Soldier>();


    public static MainLogicUnit FindMinDisEnemyTarget(MainLogicUnit self, TargetCfg cfg) {
        MainLogicUnit target = null;
        var targetTeam = GetTargetTeam(self, cfg);

        int count = targetTeam.Count;
        var selfPos = self.LogicPos;
        PEInt len = 0;
        for(var i = 0; i < count; i++) {
            var sumRaius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius + self.unitData.unitConfig.colliderConfig.mRadius;
            var tempLen = (targetTeam[i].LogicPos - selfPos).magnitude - sumRaius;
            if (len != 0 && tempLen >= len) continue;
            len = tempLen;
            target = targetTeam[i];
        }
        return target;
    }

    #region 多个目标查找
    public static List<MainLogicUnit> FindMulipleTargetByRule(MainLogicUnit self, TargetCfg cfg, PEVector3 pos) {
        var searchTeam = GetTargetTeam(self, cfg);
        List<MainLogicUnit> targetList = null;
        switch(cfg.selectRule) {
            case SelectRuleEnum.TargetClosetMultiple:
                targetList = FindRangeDisTargetInTeam(self, searchTeam, (PEInt)cfg.selectRange);
                break;
            case SelectRuleEnum.PositionClosestMultiple:
                targetList = FindRangeDisTargetInPos(pos, searchTeam, (PEInt)cfg.selectRange);
                break;
            case SelectRuleEnum.Hero:
                targetList = new List<MainLogicUnit>();
                targetList.AddRange(searchTeam);
                break;
            default:
                Debug.LogError("select target error,check your target cfg.");
                break;
        }
        return targetList;
    }

    /// <summary>
    /// 指定列表中，离指定目标角色半径范围的所有目标
    /// </summary>
    public static List<MainLogicUnit> FindRangeDisTargetInTeam(MainLogicUnit self, List<MainLogicUnit> targetTeam, PEInt range) {
        if(targetTeam == null || range < 0) {
            return null;
        }

        List<MainLogicUnit> targetList = new List<MainLogicUnit>();
        int count = targetTeam.Count;
        PEVector3 selfPos = self.LogicPos;
        for(int i = 0; i < count; i++) {
            PEInt sumRaius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius + self.unitData.unitConfig.colliderConfig.mRadius;
            PEInt sqrLen = (targetTeam[i].LogicPos - selfPos).sqrMagnitude;
            if(sqrLen < (range + sumRaius) * (range + sumRaius)) {
                targetList.Add(targetTeam[i]);
            }
        }
        return targetList;
    }
    /// <summary>
    /// 指定列表中，离指定目标点位置半径范围的所有目标
    /// </summary>
    public static List<MainLogicUnit> FindRangeDisTargetInPos(PEVector3 pos, List<MainLogicUnit> targetTeam, PEInt range) {
        if(targetTeam == null || range < 0) {
            return null;
        }

        List<MainLogicUnit> targetList = new List<MainLogicUnit>();
        int count = targetTeam.Count;
        for(int i = 0; i < count; i++) {
            PEInt radius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius;
            PEInt sqrLen = (targetTeam[i].LogicPos - pos).sqrMagnitude;
            if(sqrLen < (range + radius) * (range + radius)) {
                targetList.Add(targetTeam[i]);
            }
        }
        return targetList;
    }

    #endregion

    #region 单个目标查找 
    public static MainLogicUnit FindSingleTargetByRule(MainLogicUnit self, TargetCfg cfg, PEVector3 pos) {
        List<MainLogicUnit> serchTeam = GetTargetTeam(self, cfg);
        switch(cfg.selectRule) {
            case SelectRuleEnum.MinHPValue:
                //TODO
                break;
            case SelectRuleEnum.MinHPPercent:
                //TODO
                break;
            case SelectRuleEnum.TargetClosestSingle:
                return FindMinDisTargetInTeam(self, serchTeam, (PEInt)cfg.selectRange);
            case SelectRuleEnum.PositionClosestSingle:
                return FindMinDisTargetInPos(pos, serchTeam, (PEInt)cfg.selectRange);
            default:
                Debug.LogError("select target error, check you target cfg.");
                break;
        }
        return null;
    }

    public static MainLogicUnit FindMinDisTargetInTeam(MainLogicUnit self, List<MainLogicUnit> targetTeam, PEInt range) {
        if(targetTeam == null || range < 0) {
            return null;
        }
        MainLogicUnit target = null;
        int count = targetTeam.Count;
        var selfPos = self.LogicPos;
        PEInt len = 0;
        for(int i = 0; i < count; i++) {
            var sumRaius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius + self.unitData.unitConfig.colliderConfig.mRadius;
            var tempLen = (targetTeam[i].LogicPos - selfPos).magnitude - sumRaius;
            if (len != 0 && tempLen >= len) continue;
            len = tempLen;
            target = targetTeam[i];
        }

        return len < range ? target : null;
    }

    static MainLogicUnit FindMinDisTargetInPos(PEVector3 pos, List<MainLogicUnit> targetTeam, PEInt range) {
        if(targetTeam == null) {
            return null;
        }
        MainLogicUnit target = null;
        var count = targetTeam.Count;
        PEInt len = 0;
        for(var i = 0; i < count; i++) {
            PEInt radius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius;
            PEInt tempLen = (targetTeam[i].LogicPos - pos).magnitude - radius;
            if(len == 0 || tempLen < len) {
                len = tempLen;
                target = targetTeam[i];
            }
        }

        return len < range ? target : null;
    }
    #endregion

    static List<MainLogicUnit> GetTargetTeam(MainLogicUnit self, TargetCfg cfg) {
        var targetList = new List<MainLogicUnit>();
        if(self.IsTeam(TeamEnum.Blue))
        {
            switch (cfg.targetTeam)
            {
                case TargetTeamEnum.Friend:
                {
                    //blue
                    if(ContainTargetType(cfg, UnitTypeEnum.Hero)) {
                        targetList.AddRange(blueTeamHero);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Tower)) {
                        targetList.AddRange(blueTeamTower);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Soldier)) {
                        targetList.AddRange(blueTeamSoldier);
                    }

                    break;
                }
                case TargetTeamEnum.Enemy:
                {
                    //red
                    if(ContainTargetType(cfg, UnitTypeEnum.Hero)) {
                        targetList.AddRange(redTeamHero);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Tower)) {
                        targetList.AddRange(redTeamTower);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Soldier)) {
                        targetList.AddRange(redTeamSoldier);
                    }

                    break;
                }
                default:
                    Debug.LogError("TargetTeamEnum is unKnow.");
                    break;
            }
        }
        else if(self.IsTeam(TeamEnum.Red))
        {
            switch (cfg.targetTeam)
            {
                case TargetTeamEnum.Friend:
                {
                    //red
                    if(ContainTargetType(cfg, UnitTypeEnum.Hero)) {
                        targetList.AddRange(redTeamHero);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Tower)) {
                        targetList.AddRange(redTeamTower);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Soldier)) {
                        targetList.AddRange(redTeamSoldier);
                    }

                    break;
                }
                case TargetTeamEnum.Enemy:
                {
                    //blue
                    if(ContainTargetType(cfg, UnitTypeEnum.Hero)) {
                        targetList.AddRange(blueTeamHero);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Tower)) {
                        targetList.AddRange(blueTeamTower);
                    }
                    if(ContainTargetType(cfg, UnitTypeEnum.Soldier)) {
                        targetList.AddRange(blueTeamSoldier);
                    }

                    break;
                }
                default:
                    Debug.LogError("TargetTeamEnum is unKnow.");
                    break;
            }
        }
        else {
            Debug.LogError("Self Hero TeamEnum is unKnow.");
        }

        //过滤掉死亡单位
        for(var i = targetList.Count - 1; i >= 0; --i) {
            if(targetList[i].unitState == UnitStateEnum.Dead) {
                targetList.RemoveAt(i);
            }
        }
        return targetList;
    }

    public static MainLogicUnit FindMinDisTargetInPos(PEVector3 pos, MainLogicUnit[] targetTeam) {
        if(targetTeam == null) {
            return null;
        }

        MainLogicUnit target = null;
        var count = targetTeam.Length;
        PEInt len = 0;
        for(var i = 0; i < count; i++) {
            var radius = targetTeam[i].unitData.unitConfig.colliderConfig.mRadius;
            var tempLen = (targetTeam[i].LogicPos - pos).magnitude - radius;
            if(len == 0 || tempLen < len) {
                len = tempLen;
                target = targetTeam[i];
            }
        }
        return target;
    }

    private static bool ContainTargetType(TargetCfg cfg, UnitTypeEnum targetType)
    {
        return cfg.targetTypeArr.Any(t => t == targetType);
    }
}
